package edu.ccut.saturn.workflow.startWorkFlowModule.code;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import edu.ccut.saturn.component.ComponentFactory;
import edu.ccut.saturn.component.ComponentManager;
import edu.ccut.saturn.component.IComponent;
import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.SaturnData;
import edu.ccut.saturn.operation.Operation;
import edu.ccut.saturn.workflow.common.Constants;
import edu.ccut.saturn.workflow.common.WorkFlowTools;
import edu.ccut.saturn.workflow.model.ActivityInfo;
import edu.ccut.saturn.workflow.model.ManInfo;
import edu.ccut.saturn.workflow.model.WorkFlowInfo;

public class ActivateManualActivity implements IActivateActivity {

	@SuppressWarnings("unchecked")
	public void activate(IParameterContext parameterContext) throws Exception {
		// 获取参数
		SaturnData workFlowInstance = (SaturnData) parameterContext
				.getParameterValue(0);
		WorkFlowInfo workFlowInfo = (WorkFlowInfo) parameterContext
				.getParameterValue(1);
		HashMap<String, String> workFlowParamMap = (HashMap<String, String>) parameterContext
				.getParameterValue(2);
		// previousActivityInstance 启动时：开始活动节点；完成时：完成活动实例
		SaturnData previousActivityInstance = (SaturnData) parameterContext
				.getParameterValue(3);
		// 当前活动定义对象
		ActivityInfo currentActivityInfo = (ActivityInfo) parameterContext
				.getParameterValue(5);
		Connection conn = parameterContext.getConnection();
		// 获得当前活动数据项并附值
		SaturnData currentActivityInstance = WorkFlowTools.getActivityInstance(
				workFlowInstance, currentActivityInfo, conn);
		// 先插入人工活动，否则得不到activity_instance_id
		// 核心操作＝＝＝＝插入人工活动实例
		Operation.dataBase().insert(currentActivityInstance,
				parameterContext.getConnection());
		// 核心操作＝＝＝＝插入流转实例
		SaturnData transitionInstance = WorkFlowTools.getTransitionInstance(
				conn, previousActivityInstance, currentActivityInstance);
		Operation.dataBase().insert(transitionInstance, conn);

		// TODO 插入活动后判断活动是否有越期限制 ，如果有就插入计时器一个任务，并定时修改任务越期标识
		// 处理计时器任务
		// 1 插入计时器表 用于保存计时器任务所必需的属性

		// 2 启动计时器任务 ,当任务越期时修改越期标识
		// String limit_number = activityInstance.get("limit_number") + "";
		// if (!"0".equals(limit_number)) {
		// setTimeoutFlagTimerTask(parameterContext, activityInstance);
		// }
		// 3 可以扩展发通知定时器（sms，email）
	
		// 前一活动是开始活动时，由于开始活动没有工作项需要创建临时workItemInstance
		// 判断当前流程实例是否在数据库中存在，如果存在，说明当前活动前一活动不是开始活动
/*		String sql = "select count(*) from wf_workitem_instance where process_instance_id='"
				+ previousActivityInstance.get("process_instance_id") + "'";*/
		//int count = Operation.dataBase().queryCountBySQL(sql, conn);
		int count = 0;
		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("process_instance_id", previousActivityInstance.get("process_instance_id")+"");
		ArrayList<SaturnData> result = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_COUNT, 
							"GET_COUNT_WORKITENS_BY_PEOCESSINSTANCEID", paramMap, conn);
		if(result!=null){
			count = Integer.parseInt(result.get(0).get("count")+"");
		}
		
		SaturnData previous_workitem_instance = null;
		if (count == 0) {// 是开始节点
			previous_workitem_instance = WorkFlowTools.getWorkItemInstance();
			previous_workitem_instance.setString("assistant", workFlowInstance
					.getString("creator"));
			previous_workitem_instance.setString("assistant_name",
					workFlowInstance.getString("creator_name"));
			previous_workitem_instance.setString("assistant_department",
					workFlowInstance.getString("creator_department"));

		} else {// 其他节点
			previous_workitem_instance = WorkFlowTools.getWorkItemInstance();
			previous_workitem_instance.setString("assistant", workFlowParamMap
					.get("userSerialNo"));
			previous_workitem_instance.setString("assistant_name",
					workFlowParamMap.get("userName"));
			previous_workitem_instance.setString("assistant_department",
					workFlowParamMap.get("userDepartment"));
		}
		String isMulWorkItems = currentActivityInfo.getIsMulWorkItems();
		if (isMulWorkItems.equals(Constants.ACTIVITY_ISMULWORKITEMS)) {
			// 获得工作项实例
			SaturnData workItemInstance = WorkFlowTools.getWorkItemInstance(
					workFlowInstance, currentActivityInstance,
					previous_workitem_instance, currentActivityInfo,
					workFlowInfo, parameterContext.getConnection());
			// 插入工作项实例表
			Operation.dataBase().insert(workItemInstance, conn);
			// 获得工作项参与者列表
			IParticipantGeter pg = WorkFlowInstanceFactory
					.getParticipantGeter(((ManInfo) currentActivityInfo)
							.getObtainFromActivityRadioButton());
			List<SaturnData> participantInstanceList = pg.getParticipant(
					workItemInstance, currentActivityInfo, parameterContext);
			List<SaturnData> participantsList = getFactParticipants(participantInstanceList, 
					workFlowInstance, currentActivityInfo, conn);
			//去重
			Set participantInstanceSet = new HashSet();	
			Set participantSet = new HashSet();	
			//正常参与者间去重
			for(SaturnData participantInstance : participantInstanceList){
				participantInstanceSet.add(participantInstance);
			}			
			//代理人间去重
			for(SaturnData participantInstance : participantsList){
				participantSet.add(participantInstance);
			}
			//代理人和正常参与者间去重，二者之间只保留正常的参与者，不再添加代理人
			for(SaturnData participantInstance : participantInstanceList){
				for(SaturnData agentParticipant : participantsList){
					if(agentParticipant.getString("participant").equals(participantInstance.getString("participant"))){
						participantSet.remove(agentParticipant);
					}
				}
			}
			
			//插入正常的参与者
			Iterator<SaturnData> iteratorComm = participantInstanceSet.iterator();
			while (iteratorComm.hasNext()) {
				SaturnData participantInstance = iteratorComm.next();
				participantInstance.set("workitemid", workItemInstance
						.get("workitem_id"));
				participantInstance.set("workitemstate", "0");
				participantInstance.set("partiintype", "Y");
				//TODO 插入extend1为了保存实际的参与者（即委托人）
				participantInstance.set("extend1", participantInstance.get("participant"));
				Operation.dataBase().insert(participantInstance, conn);
			}
			//插入代理人
			Iterator<SaturnData> iteratorFact = participantSet.iterator();
			while (iteratorFact.hasNext()) {
				SaturnData participantInstance = iteratorFact.next();
				participantInstance.set("workitemid", workItemInstance
						.get("workitem_id"));
				participantInstance.set("workitemstate", Constants.WORKITEM_BIZSTATE_AGENT);
				participantInstance.set("partiintype", "Y");
				Operation.dataBase().insert(participantInstance, conn);
			}
		/*	for (SaturnData participantInstance : participantsList) {
				participantInstance.set("workitemid", workItemInstance
						.get("workitem_id"));
				//TODO 设值参与的工作项状态
				participantInstance.set("workitemstate", "0");
				//TODO 设值参与者的权限
				participantInstance.set("partiintype", "Y");
				Operation.dataBase().insert(participantInstance, conn);
			}*/
		} else {
			// 获得工作项参与者列表
			IParticipantGeter pg = WorkFlowInstanceFactory
					.getParticipantGeter(((ManInfo) currentActivityInfo)
							.getObtainFromActivityRadioButton());
			List<SaturnData> participantInstanceList = pg.getParticipant(
					//暂时传入workFlowInstance，以传入process_instance_id
					workFlowInstance, 
					currentActivityInfo,parameterContext);
			
			// 插入工作项参与者
			for (SaturnData participantInstance : participantInstanceList) {
				// 获得工作项实例,为每一参与者设置工作项
				SaturnData workItemInstance = WorkFlowTools.getWorkItemInstance(
						workFlowInstance, currentActivityInstance,
						previous_workitem_instance, currentActivityInfo,
						workFlowInfo, parameterContext.getConnection());
				// 插入工作项实例表
				Operation.dataBase().insert(workItemInstance, conn);
				//插入参与者
				participantInstance.set("workitemid", workItemInstance.get("workitem_id"));
				participantInstance.set("partiintype", "Y");
				participantInstance.set("extend1", participantInstance.get("participant"));
				participantInstance.set("workitemstate", Constants.WORKITEM_BIZSTATE_COMMON);//正常
				Operation.dataBase().insert(participantInstance, conn);
				
				ArrayList<SaturnData> agentParticipantList = getAgentInstListByParticipant(participantInstance, workFlowInstance, currentActivityInfo, conn);
				for(SaturnData agentParticipant:agentParticipantList){
					agentParticipant.set("workitemid", workItemInstance
							.get("workitem_id"));
					agentParticipant.set("partiintype", "Y");
					agentParticipant.set("workitemstate", Constants.WORKITEM_BIZSTATE_AGENT);//代理
					Operation.dataBase().insert(agentParticipant, conn);
				}
			}
		}
		
		//执行定时器，标记活动和工作项超时
		String final_time  = currentActivityInstance.getString("final_time");
		if(!"".equals(final_time)&&final_time!=null){
			IParameterContext tempContext = ComponentFactory.createParameterContext();
			tempContext.addParameter(final_time, java.util.HashMap.class);
			tempContext.addParameter(currentActivityInstance, edu.ccut.saturn.component.SaturnData.class);
			IComponent timer = ComponentManager.getInstance().getComponent("edu.ccut.saturn.workflow::/finishTaskModule/logic/MarkActivityTimeoutTimer.logic");
			timer.execute(tempContext);
		}
	}
	
	//查询当前参与者设置有效的完全代理
	private ArrayList<SaturnData> getAgentAll(SaturnData participantInstance,Connection conn) 
			throws Exception{
		String sys_time = Operation.baseService().GetSystemTime();
		HashMap<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("agent_from", participantInstance.get("participant")+"");
		paramMap.put("sys_time", sys_time);
		paramMap.put("type", "ALL");
		
		ArrayList<SaturnData> agentInstList = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_AGENT, 
				"GET_AVAILABILITY_AGENT", paramMap, conn);
		
 		return agentInstList; 
	}
	
	//如果当前流程是例外流程，则从完全代理List中删除
	private ArrayList<SaturnData> getAgentAllInstList(SaturnData workFlowInstance,SaturnData participantInstance,Connection conn)       
			throws Exception{
		ArrayList<SaturnData> agentInstList = getAgentAll(participantInstance, conn);
		if(agentInstList!=null){
			for(int i=0;i<agentInstList.size();i++){	
				HashMap<String,Object> paramMap = new HashMap<String,Object>();
				paramMap.put("agent_id", agentInstList.get(i).get("agent_id")+"");
				paramMap.put("type","PROCESS");
				paramMap.put("id", workFlowInstance.get("process_define_id")+"");
				
				ArrayList<SaturnData> agentitemInstList = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_AGENTITEM, 
						"GET_AGENTITEM", paramMap, conn);
				if(agentitemInstList!=null){
					agentInstList.remove(i);
					i=i-1;
				}
			}
		}
		return agentInstList;
	}
	
	
	//查询当前参与者设置部分代理
	private ArrayList<SaturnData> getAgentPart(SaturnData participantInstance,Connection conn) 
			throws Exception{
		String sys_time = Operation.baseService().GetSystemTime();
		HashMap<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("agent_from", participantInstance.get("participant")+"");
		paramMap.put("sys_time", sys_time);
		paramMap.put("type", "PART");
		
		ArrayList<SaturnData> agentInstList = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_AGENT, 
				"GET_AVAILABILITY_AGENT", paramMap, conn);
		
 		return agentInstList; 
	}
	
	//取得部分代理有效的委托流程
	private ArrayList<SaturnData> getAgentPartInstList(SaturnData workFlowInstance,ActivityInfo currentActivityInfo,
			SaturnData participantInstance,Connection conn)       
			throws Exception{
		ArrayList<SaturnData> agentPartInstList = new ArrayList<SaturnData>();
		List<SaturnData> agentInstList = getAgentPart(participantInstance, conn);
		if(agentInstList!=null){
			for(SaturnData agentInst:agentInstList){
				HashMap<String,Object> paramMap = new HashMap<String,Object>();
				paramMap.put("agent_id",agentInst.get("agent_id")+"");
				paramMap.put("type","PROCESS");
				paramMap.put("id", workFlowInstance.get("process_define_id")+"");
				
				ArrayList<SaturnData> proAgentitemInstList = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_AGENTITEM, 
						"GET_AGENTITEM", paramMap, conn);
				
				if(proAgentitemInstList!=null){
					agentPartInstList.add(agentInst);
				}
				
				paramMap.put("agent_id",agentInst.get("agent_id")+"");
				paramMap.put("type","ACTIVITY");
				paramMap.put("id", currentActivityInfo.getId()+"|"+workFlowInstance.get("process_define_id"));
				
				ArrayList<SaturnData> actAgentitemInstList = Operation.dataBase().queryBySaturnSql(Constants.SATURNDATA_WF_AGENTITEM, 
						"GET_AGENTITEM", paramMap, conn);
				
				if(actAgentitemInstList!=null){
					agentPartInstList.add(agentInst);
				}
			}
		}
		return agentPartInstList;
	}
	
	//TODO 代理权限的传递问题
	//在活动的参与者中添加有效代理的代理人
	private List<SaturnData> getFactParticipants(List<SaturnData> participantInstanceList,
			SaturnData workFlowInstance,ActivityInfo currentActivityInfo,Connection conn)
			throws Exception{
		ArrayList<SaturnData> participants = new ArrayList<SaturnData>();
		for(SaturnData participantInstance:participantInstanceList){
			participants.addAll(
					getAgentInstListByParticipant(participantInstance, 
								workFlowInstance, currentActivityInfo, conn));
		}		
		return participants;
	}
	
	//得到委托人的代理人
	private ArrayList<SaturnData> getAgentInstListByParticipant(SaturnData participantInstance,SaturnData workFlowInstance,ActivityInfo currentActivityInfo,Connection conn) throws Exception{
		ArrayList<SaturnData> agentInstList = new ArrayList<SaturnData>();
		ArrayList<SaturnData> participants = new ArrayList<SaturnData>();
		ArrayList<SaturnData> agentAllList = getAgentAllInstList(workFlowInstance, participantInstance, conn);
		ArrayList<SaturnData> agentPartList = getAgentPartInstList(workFlowInstance, currentActivityInfo, participantInstance, conn);
		
		if(agentPartList.size()!=0){
			agentInstList.addAll(agentPartList);
		}
		if(agentAllList!=null){
			agentInstList.addAll(agentAllList);
		}
		
		for(SaturnData agentInst:agentInstList){
			String id=agentInst.get("agent_to")+"";
			String type=agentInst.get("agent_to_type")+"";
			List<SaturnData> userDataList = WorkFlowTools.getUserDataListByTypeAndId(type, id, conn);
			for(SaturnData userData:userDataList){
				SaturnData wiParticipantData = WorkFlowTools.getParticipantInstanceWithValues(userData.getString("id"), userData.getString("username"));
				//TODO 标记委托人
				wiParticipantData.set("extend1", agentInst.getString("agent_from"));
				participants.add(wiParticipantData);
			}
		}
		
		return participants;
	}
}
